#ifndef SYSTEM_HPP
#define SYSTEM_HPP

#include <stdint.h>

/************ Cortex M4 ************/

/* Nested Vectored Interrupt Controller. */

typedef struct {
    volatile uint32_t ISER[8];  /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
    uint32_t RESERVED0[24];
    volatile uint32_t ICER[8];  /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
    uint32_t RSERVED1[24];
    volatile uint32_t ISPR[8];  /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
    uint32_t RESERVED2[24];
    volatile uint32_t ICPR[8];  /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
    uint32_t RESERVED3[24];
    volatile uint32_t IABR[8];  /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
    uint32_t RESERVED4[56];
    volatile uint8_t  IP[240];  /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
    uint32_t RESERVED5[644];
    volatile  uint32_t STIR;    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
} NVIC_Register_t;

/* System Control Block. */

typedef struct {
    volatile uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
    volatile uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
    volatile uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */
    volatile uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
    volatile uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
    volatile uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
    volatile uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */
    volatile uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
    volatile uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */
    volatile uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */
    volatile uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */
    volatile uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */
    volatile uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */
    volatile uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */
    volatile uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */
    volatile uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */
    volatile uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */
    volatile uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */
    volatile uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */
    uint32_t RESERVED0[5];
    volatile uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
} SCB_Register_t;

/* System Timer. */

typedef struct {
    volatile uint32_t CTRL;                    /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
    volatile uint32_t LOAD;                    /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register       */
    volatile uint32_t VAL;                     /*!< Offset: 0x008 (R/W)  SysTick Current Value Register      */
    volatile uint32_t CALIB;                   /*!< Offset: 0x00C (R/ )  SysTick Calibration Register        */
} SysTick_Register_t;

/* Analog to Digital Converter. */

typedef struct {
    volatile uint32_t SR;     /*!< ADC status register,                         Address offset: 0x00 */
    volatile uint32_t CR1;    /*!< ADC control register 1,                      Address offset: 0x04 */      
    volatile uint32_t CR2;    /*!< ADC control register 2,                      Address offset: 0x08 */
    volatile uint32_t SMPR1;  /*!< ADC sample time register 1,                  Address offset: 0x0C */
    volatile uint32_t SMPR2;  /*!< ADC sample time register 2,                  Address offset: 0x10 */
    volatile uint32_t JOFR1;  /*!< ADC injected channel data offset register 1, Address offset: 0x14 */
    volatile uint32_t JOFR2;  /*!< ADC injected channel data offset register 2, Address offset: 0x18 */
    volatile uint32_t JOFR3;  /*!< ADC injected channel data offset register 3, Address offset: 0x1C */
    volatile uint32_t JOFR4;  /*!< ADC injected channel data offset register 4, Address offset: 0x20 */
    volatile uint32_t HTR;    /*!< ADC watchdog higher threshold register,      Address offset: 0x24 */
    volatile uint32_t LTR;    /*!< ADC watchdog lower threshold register,       Address offset: 0x28 */
    volatile uint32_t SQR1;   /*!< ADC regular sequence register 1,             Address offset: 0x2C */
    volatile uint32_t SQR2;   /*!< ADC regular sequence register 2,             Address offset: 0x30 */
    volatile uint32_t SQR3;   /*!< ADC regular sequence register 3,             Address offset: 0x34 */
    volatile uint32_t JSQR;   /*!< ADC injected sequence register,              Address offset: 0x38 */
    volatile uint32_t JDR1;   /*!< ADC injected data register 1,                Address offset: 0x3C */
    volatile uint32_t JDR2;   /*!< ADC injected data register 2,                Address offset: 0x40 */
    volatile uint32_t JDR3;   /*!< ADC injected data register 3,                Address offset: 0x44 */
    volatile uint32_t JDR4;   /*!< ADC injected data register 4,                Address offset: 0x48 */
    volatile uint32_t DR;     /*!< ADC regular data register,                   Address offset: 0x4C */
} ADC_Register_t;

typedef struct {
    volatile uint32_t CSR;    /*!< ADC Common status register,                  Address offset: ADC1 base address + 0x300 */
    volatile uint32_t CCR;    /*!< ADC common control register,                 Address offset: ADC1 base address + 0x304 */
    volatile uint32_t CDR;    /*!< ADC common regular data register for dual
                                AND triple modes,                            Address offset: ADC1 base address + 0x308 */
} ADC_Common_Register_t;

/* Controller Area Network TxMailBox. */

typedef struct {
    volatile uint32_t TIR;  /*!< CAN TX mailbox identifier register */
    volatile uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */
    volatile uint32_t TDLR; /*!< CAN mailbox data low register */
    volatile uint32_t TDHR; /*!< CAN mailbox data high register */
} CAN_TxMailBox_Register_t;

/* Controller Area Network FIFOMailBox. */

typedef struct {
    volatile uint32_t RIR;  /*!< CAN receive FIFO mailbox identifier register */
    volatile uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */
    volatile uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */
    volatile uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */
} CAN_FIFOMailBox_Register_t;

/* Controller Area Network FilterRegister. */

typedef struct {
    volatile uint32_t FR1; /*!< CAN Filter bank register 1 */
    volatile uint32_t FR2; /*!< CAN Filter bank register 1 */
} CAN_FilterRegister_Register_t;

/* Controller Area Network. */

typedef struct {
    volatile uint32_t              MCR;                 /*!< CAN master control register,         Address offset: 0x00          */
    volatile uint32_t              MSR;                 /*!< CAN master status register,          Address offset: 0x04          */
    volatile uint32_t              TSR;                 /*!< CAN transmit status register,        Address offset: 0x08          */
    volatile uint32_t              RF0R;                /*!< CAN receive FIFO 0 register,         Address offset: 0x0C          */
    volatile uint32_t              RF1R;                /*!< CAN receive FIFO 1 register,         Address offset: 0x10          */
    volatile uint32_t              IER;                 /*!< CAN interrupt enable register,       Address offset: 0x14          */
    volatile uint32_t              ESR;                 /*!< CAN error status register,           Address offset: 0x18          */
    volatile uint32_t              BTR;                 /*!< CAN bit timing register,             Address offset: 0x1C          */
    uint32_t                   RESERVED0[88];       /*!< Reserved, 0x020 - 0x17F                                            */
    CAN_TxMailBox_Register_t      sTxMailBox[3];       /*!< CAN Tx MailBox,                      Address offset: 0x180 - 0x1AC */
    CAN_FIFOMailBox_Register_t    sFIFOMailBox[2];     /*!< CAN FIFO MailBox,                    Address offset: 0x1B0 - 0x1CC */
    uint32_t                   RESERVED1[12];       /*!< Reserved, 0x1D0 - 0x1FF                                            */
    volatile uint32_t              FMR;                 /*!< CAN filter master register,          Address offset: 0x200         */
    volatile uint32_t              FM1R;                /*!< CAN filter mode register,            Address offset: 0x204         */
    uint32_t                   RESERVED2;           /*!< Reserved, 0x208                                                    */
    volatile uint32_t              FS1R;                /*!< CAN filter scale register,           Address offset: 0x20C         */
    uint32_t                   RESERVED3;           /*!< Reserved, 0x210                                                    */
    volatile uint32_t              FFA1R;               /*!< CAN filter FIFO assignment register, Address offset: 0x214         */
    uint32_t                   RESERVED4;           /*!< Reserved, 0x218                                                    */
    volatile uint32_t              FA1R;                /*!< CAN filter activation register,      Address offset: 0x21C         */
    uint32_t                   RESERVED5[8];        /*!< Reserved, 0x220-0x23F                                              */ 
    CAN_FilterRegister_Register_t sFilterRegister[28]; /*!< CAN Filter Register,                 Address offset: 0x240-0x31C   */
} CAN_Register_t;

/* CRC Calculation Unit. */

typedef struct {
    volatile uint32_t DR;         /*!< CRC Data register,             Address offset: 0x00 */
    volatile uint8_t  IDR;        /*!< CRC Independent data register, Address offset: 0x04 */
    uint8_t       RESERVED0;  /*!< Reserved, 0x05                                      */
    uint16_t      RESERVED1;  /*!< Reserved, 0x06                                      */
    volatile uint32_t CR;         /*!< CRC Control register,          Address offset: 0x08 */
} CRC_Register_t;

/* Digital to Analog Converter. */

typedef struct
{
    volatile uint32_t CR;       /*!< DAC control register,                                    Address offset: 0x00 */
    volatile uint32_t SWTRIGR;  /*!< DAC software trigger register,                           Address offset: 0x04 */
    volatile uint32_t DHR12R1;  /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */
    volatile uint32_t DHR12L1;  /*!< DAC channel1 12-bit left aligned data holding register,  Address offset: 0x0C */
    volatile uint32_t DHR8R1;   /*!< DAC channel1 8-bit right aligned data holding register,  Address offset: 0x10 */
    volatile uint32_t DHR12R2;  /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */
    volatile uint32_t DHR12L2;  /*!< DAC channel2 12-bit left aligned data holding register,  Address offset: 0x18 */
    volatile uint32_t DHR8R2;   /*!< DAC channel2 8-bit right-aligned data holding register,  Address offset: 0x1C */
    volatile uint32_t DHR12RD;  /*!< Dual DAC 12-bit right-aligned data holding register,     Address offset: 0x20 */
    volatile uint32_t DHR12LD;  /*!< DUAL DAC 12-bit left aligned data holding register,      Address offset: 0x24 */
    volatile uint32_t DHR8RD;   /*!< DUAL DAC 8-bit right aligned data holding register,      Address offset: 0x28 */
    volatile uint32_t DOR1;     /*!< DAC channel1 data output register,                       Address offset: 0x2C */
    volatile uint32_t DOR2;     /*!< DAC channel2 data output register,                       Address offset: 0x30 */
    volatile uint32_t SR;       /*!< DAC status register,                                     Address offset: 0x34 */
} DAC_TypeDef;

/* Debug. */

typedef struct {
    volatile uint32_t IDCODE;  /*!< MCU device ID code,               Address offset: 0x00 */
    volatile uint32_t CR;      /*!< Debug MCU configuration register, Address offset: 0x04 */
    volatile uint32_t APB1FZ;  /*!< Debug MCU APB1 freeze register,   Address offset: 0x08 */
    volatile uint32_t APB2FZ;  /*!< Debug MCU APB2 freeze register,   Address offset: 0x0C */
}DBGMCU_Register_t;

/* DCMI. */

typedef struct {
    volatile uint32_t CR;       /*!< DCMI control register 1,                       Address offset: 0x00 */
    volatile uint32_t SR;       /*!< DCMI status register,                          Address offset: 0x04 */
    volatile uint32_t RISR;     /*!< DCMI raw interrupt status register,            Address offset: 0x08 */
    volatile uint32_t IER;      /*!< DCMI interrupt enable register,                Address offset: 0x0C */
    volatile uint32_t MISR;     /*!< DCMI masked interrupt status register,         Address offset: 0x10 */
    volatile uint32_t ICR;      /*!< DCMI interrupt clear register,                 Address offset: 0x14 */
    volatile uint32_t ESCR;     /*!< DCMI embedded synchronization code register,   Address offset: 0x18 */
    volatile uint32_t ESUR;     /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */
    volatile uint32_t CWSTRTR;  /*!< DCMI crop window start,                        Address offset: 0x20 */
    volatile uint32_t CWSIZER;  /*!< DCMI crop window size,                         Address offset: 0x24 */
    volatile uint32_t DR;       /*!< DCMI data register,                            Address offset: 0x28 */
} DCMI_Register_t;

/* DMA Controller. */

typedef struct {
    volatile uint32_t CR;     /*!< DMA stream x configuration register      */
    volatile uint32_t NDTR;   /*!< DMA stream x number of data register     */
    volatile uint32_t PAR;    /*!< DMA stream x peripheral address register */
    volatile uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */
    volatile uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */
    volatile uint32_t FCR;    /*!< DMA stream x FIFO control register       */
} DMA_Stream_Register_t;

typedef struct {
    volatile uint32_t LISR;   /*!< DMA low interrupt status register,      Address offset: 0x00 */
    volatile uint32_t HISR;   /*!< DMA high interrupt status register,     Address offset: 0x04 */
    volatile uint32_t LIFCR;  /*!< DMA low interrupt flag clear register,  Address offset: 0x08 */
    volatile uint32_t HIFCR;  /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
} DMA_Register_t;

/* DMA2D Controller. */

typedef struct {
    volatile uint32_t CR;            /*!< DMA2D Control Register,                         Address offset: 0x00 */
    volatile uint32_t ISR;           /*!< DMA2D Interrupt Status Register,                Address offset: 0x04 */
    volatile uint32_t IFCR;          /*!< DMA2D Interrupt Flag Clear Register,            Address offset: 0x08 */
    volatile uint32_t FGMAR;         /*!< DMA2D Foreground Memory Address Register,       Address offset: 0x0C */
    volatile uint32_t FGOR;          /*!< DMA2D Foreground Offset Register,               Address offset: 0x10 */
    volatile uint32_t BGMAR;         /*!< DMA2D Background Memory Address Register,       Address offset: 0x14 */
    volatile uint32_t BGOR;          /*!< DMA2D Background Offset Register,               Address offset: 0x18 */
    volatile uint32_t FGPFCCR;       /*!< DMA2D Foreground PFC Control Register,          Address offset: 0x1C */
    volatile uint32_t FGCOLR;        /*!< DMA2D Foreground Color Register,                Address offset: 0x20 */
    volatile uint32_t BGPFCCR;       /*!< DMA2D Background PFC Control Register,          Address offset: 0x24 */
    volatile uint32_t BGCOLR;        /*!< DMA2D Background Color Register,                Address offset: 0x28 */
    volatile uint32_t FGCMAR;        /*!< DMA2D Foreground CLUT Memory Address Register,  Address offset: 0x2C */
    volatile uint32_t BGCMAR;        /*!< DMA2D Background CLUT Memory Address Register,  Address offset: 0x30 */
    volatile uint32_t OPFCCR;        /*!< DMA2D Output PFC Control Register,              Address offset: 0x34 */
    volatile uint32_t OCOLR;         /*!< DMA2D Output Color Register,                    Address offset: 0x38 */
    volatile uint32_t OMAR;          /*!< DMA2D Output Memory Address Register,           Address offset: 0x3C */
    volatile uint32_t OOR;           /*!< DMA2D Output Offset Register,                   Address offset: 0x40 */
    volatile uint32_t NLR;           /*!< DMA2D Number of Line Register,                  Address offset: 0x44 */
    volatile uint32_t LWR;           /*!< DMA2D Line Watermark Register,                  Address offset: 0x48 */
    volatile uint32_t AMTCR;         /*!< DMA2D AHB Master Timer Configuration Register,  Address offset: 0x4C */
    uint32_t      RESERVED[236]; /*!< Reserved, 0x50-0x3FF */
    volatile uint32_t FGCLUT[256];   /*!< DMA2D Foreground CLUT,                          Address offset:400-7FF */
    volatile uint32_t BGCLUT[256];   /*!< DMA2D Background CLUT,                          Address offset:800-BFF */
} DMA2D_Register_t;

/* Ethernet MAC. */

typedef struct {
    volatile uint32_t MACCR;
    volatile uint32_t MACFFR;
    volatile uint32_t MACHTHR;
    volatile uint32_t MACHTLR;
    volatile uint32_t MACMIIAR;
    volatile uint32_t MACMIIDR;
    volatile uint32_t MACFCR;
    volatile uint32_t MACVLANTR;             /*    8 */
    uint32_t      RESERVED0[2];
    volatile uint32_t MACRWUFFR;             /*   11 */
    volatile uint32_t MACPMTCSR;
    uint32_t      RESERVED1[2];
    volatile uint32_t MACSR;                 /*   15 */
    volatile uint32_t MACIMR;
    volatile uint32_t MACA0HR;
    volatile uint32_t MACA0LR;
    volatile uint32_t MACA1HR;
    volatile uint32_t MACA1LR;
    volatile uint32_t MACA2HR;
    volatile uint32_t MACA2LR;
    volatile uint32_t MACA3HR;
    volatile uint32_t MACA3LR;               /*   24 */
    uint32_t      RESERVED2[40];
    volatile uint32_t MMCCR;                 /*   65 */
    volatile uint32_t MMCRIR;
    volatile uint32_t MMCTIR;
    volatile uint32_t MMCRIMR;
    volatile uint32_t MMCTIMR;               /*   69 */
    uint32_t      RESERVED3[14];
    volatile uint32_t MMCTGFSCCR;            /*   84 */
    volatile uint32_t MMCTGFMSCCR;
    uint32_t      RESERVED4[5];
    volatile uint32_t MMCTGFCR;
    uint32_t      RESERVED5[10];
    volatile uint32_t MMCRFCECR;
    volatile uint32_t MMCRFAECR;
    uint32_t      RESERVED6[10];
    volatile uint32_t MMCRGUFCR;
    uint32_t      RESERVED7[334];
    volatile uint32_t PTPTSCR;
    volatile uint32_t PTPSSIR;
    volatile uint32_t PTPTSHR;
    volatile uint32_t PTPTSLR;
    volatile uint32_t PTPTSHUR;
    volatile uint32_t PTPTSLUR;
    volatile uint32_t PTPTSAR;
    volatile uint32_t PTPTTHR;
    volatile uint32_t PTPTTLR;
    volatile uint32_t RESERVED8;
    volatile uint32_t PTPTSSR;
    uint32_t      RESERVED9[565];
    volatile uint32_t DMABMR;
    volatile uint32_t DMATPDR;
    volatile uint32_t DMARPDR;
    volatile uint32_t DMARDLAR;
    volatile uint32_t DMATDLAR;
    volatile uint32_t DMASR;
    volatile uint32_t DMAOMR;
    volatile uint32_t DMAIER;
    volatile uint32_t DMAMFBOCR;
    volatile uint32_t DMARSWTR;
    uint32_t      RESERVED10[8];
    volatile uint32_t DMACHTDR;
    volatile uint32_t DMACHRDR;
    volatile uint32_t DMACHTBAR;
    volatile uint32_t DMACHRBAR;
} ETH_Register_t;

/* External Interrupt/Event Controller. */

typedef struct {
    volatile uint32_t IMR;    /*!< EXTI Interrupt mask register,            Address offset: 0x00 */
    volatile uint32_t EMR;    /*!< EXTI Event mask register,                Address offset: 0x04 */
    volatile uint32_t RTSR;   /*!< EXTI Rising trigger selection register,  Address offset: 0x08 */
    volatile uint32_t FTSR;   /*!< EXTI Falling trigger selection register, Address offset: 0x0C */
    volatile uint32_t SWIER;  /*!< EXTI Software interrupt event register,  Address offset: 0x10 */
    volatile uint32_t PR;     /*!< EXTI Pending register,                   Address offset: 0x14 */
} EXTI_Register_t;

/* Flash Registers. */

typedef struct {
    volatile uint32_t ACR;      /*!< FLASH access control register,   Address offset: 0x00 */
    volatile uint32_t KEYR;     /*!< FLASH key register,              Address offset: 0x04 */
    volatile uint32_t OPTKEYR;  /*!< FLASH option key register,       Address offset: 0x08 */
    volatile uint32_t SR;       /*!< FLASH status register,           Address offset: 0x0C */
    volatile uint32_t CR;       /*!< FLASH control register,          Address offset: 0x10 */
    volatile uint32_t OPTCR;    /*!< FLASH option control register ,  Address offset: 0x14 */
    volatile uint32_t OPTCR1;   /*!< FLASH option control register 1, Address offset: 0x18 */
} FLASH_Register_t;

/* General Purpose I/O. */

typedef struct {
    volatile uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
    volatile uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
    volatile uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
    volatile uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
    volatile uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
    volatile uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
    volatile uint32_t BSRR;     /*!< GPIO port bit set/reset register,      Address offset: 0x18      */
    volatile uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
    volatile uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
} GPIO_Register_t;

/* System configuration controller. */

typedef struct {
    volatile uint32_t MEMRMP;       /*!< SYSCFG memory remap register,                      Address offset: 0x00      */
    volatile uint32_t PMC;          /*!< SYSCFG peripheral mode configuration register,     Address offset: 0x04      */
    volatile uint32_t EXTICR[4];    /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
    uint32_t      RESERVED[2];  /*!< Reserved, 0x18-0x1C                                                          */ 
    volatile uint32_t CMPCR;        /*!< SYSCFG Compensation cell control register,         Address offset: 0x20      */
} SYSCFG_Register_t;

/* Inter-integrated Circuit Interface. */

typedef struct {
    volatile uint16_t CR1;        /*!< I2C Control register 1,     Address offset: 0x00 */
    uint16_t      RESERVED0;  /*!< Reserved, 0x02                                   */
    volatile uint16_t CR2;        /*!< I2C Control register 2,     Address offset: 0x04 */
    uint16_t      RESERVED1;  /*!< Reserved, 0x06                                   */
    volatile uint16_t OAR1;       /*!< I2C Own address register 1, Address offset: 0x08 */
    uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                   */
    volatile uint16_t OAR2;       /*!< I2C Own address register 2, Address offset: 0x0C */
    uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                   */
    volatile uint16_t DR;         /*!< I2C Data register,          Address offset: 0x10 */
    uint16_t      RESERVED4;  /*!< Reserved, 0x12                                   */
    volatile uint16_t SR1;        /*!< I2C Status register 1,      Address offset: 0x14 */
    uint16_t      RESERVED5;  /*!< Reserved, 0x16                                   */
    volatile uint16_t SR2;        /*!< I2C Status register 2,      Address offset: 0x18 */
    uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                   */
    volatile uint16_t CCR;        /*!< I2C Clock control register, Address offset: 0x1C */
    uint16_t      RESERVED7;  /*!< Reserved, 0x1E                                   */
    volatile uint16_t TRISE;      /*!< I2C TRISE register,         Address offset: 0x20 */
    uint16_t      RESERVED8;  /*!< Reserved, 0x22                                   */
    volatile uint16_t FLTR;       /*!< I2C FLTR register,          Address offset: 0x24 */
    uint16_t      RESERVED9;  /*!< Reserved, 0x26                                   */
} I2C_Register_t;

/* Independent Watchdog. */

typedef struct {
    volatile uint32_t KR;   /*!< IWDG Key register,       Address offset: 0x00 */
    volatile uint32_t PR;   /*!< IWDG Prescaler register, Address offset: 0x04 */
    volatile uint32_t RLR;  /*!< IWDG Reload register,    Address offset: 0x08 */
    volatile uint32_t SR;   /*!< IWDG Status register,    Address offset: 0x0C */
} IWDG_Register_t;

/* LCD-TFT Display Controller. */

typedef struct {
    uint32_t      RESERVED0[2];  /*!< Reserved, 0x00-0x04 */
    volatile uint32_t SSCR;          /*!< LTDC Synchronization Size Configuration Register,    Address offset: 0x08 */
    volatile uint32_t BPCR;          /*!< LTDC Back Porch Configuration Register,              Address offset: 0x0C */
    volatile uint32_t AWCR;          /*!< LTDC Active Width Configuration Register,            Address offset: 0x10 */
    volatile uint32_t TWCR;          /*!< LTDC Total Width Configuration Register,             Address offset: 0x14 */
    volatile uint32_t GCR;           /*!< LTDC Global Control Register,                        Address offset: 0x18 */
    uint32_t      RESERVED1[2];  /*!< Reserved, 0x1C-0x20 */
    volatile uint32_t SRCR;          /*!< LTDC Shadow Reload Configuration Register,           Address offset: 0x24 */
    uint32_t      RESERVED2[1];  /*!< Reserved, 0x28 */
    volatile uint32_t BCCR;          /*!< LTDC Background Color Configuration Register,        Address offset: 0x2C */
    uint32_t      RESERVED3[1];  /*!< Reserved, 0x30 */
    volatile uint32_t IER;           /*!< LTDC Interrupt Enable Register,                      Address offset: 0x34 */
    volatile uint32_t ISR;           /*!< LTDC Interrupt Status Register,                      Address offset: 0x38 */
    volatile uint32_t ICR;           /*!< LTDC Interrupt Clear Register,                       Address offset: 0x3C */
    volatile uint32_t LIPCR;         /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */
    volatile uint32_t CPSR;          /*!< LTDC Current Position Status Register,               Address offset: 0x44 */
    volatile uint32_t CDSR;         /*!< LTDC Current Display Status Register,                       Address offset: 0x48 */
} LTDC_Register_t; 

/* LCD-TFT Display layer x Controller. */

typedef struct {  
    volatile uint32_t CR;            /*!< LTDC Layerx Control Register                                  Address offset: 0x84 */
    volatile uint32_t WHPCR;         /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */
    volatile uint32_t WVPCR;         /*!< LTDC Layerx Window Vertical Position Configuration Register   Address offset: 0x8C */
    volatile uint32_t CKCR;          /*!< LTDC Layerx Color Keying Configuration Register               Address offset: 0x90 */
    volatile uint32_t PFCR;          /*!< LTDC Layerx Pixel Format Configuration Register               Address offset: 0x94 */
    volatile uint32_t CACR;          /*!< LTDC Layerx Constant Alpha Configuration Register             Address offset: 0x98 */
    volatile uint32_t DCCR;          /*!< LTDC Layerx Default Color Configuration Register              Address offset: 0x9C */
    volatile uint32_t BFCR;          /*!< LTDC Layerx Blending Factors Configuration Register           Address offset: 0xA0 */
    uint32_t      RESERVED0[2];  /*!< Reserved */
    volatile uint32_t CFBAR;         /*!< LTDC Layerx Color Frame Buffer Address Register               Address offset: 0xAC */
    volatile uint32_t CFBLR;         /*!< LTDC Layerx Color Frame Buffer Length Register                Address offset: 0xB0 */
    volatile uint32_t CFBLNR;        /*!< LTDC Layerx ColorFrame Buffer Line Number Register            Address offset: 0xB4 */
    uint32_t      RESERVED1[3];  /*!< Reserved */
    volatile uint32_t CLUTWR;         /*!< LTDC Layerx CLUT Write Register                               Address offset: 0x144 */
} LTDC_Layer_Register_t;

/* Power Control. */

typedef struct {
    volatile uint32_t CR;   /*!< PWR power control register,        Address offset: 0x00 */
    volatile uint32_t CSR;  /*!< PWR power control/status register, Address offset: 0x04 */
} PWR_Register_t;

/* Reset and Clock Control. */

typedef struct {
    volatile uint32_t CR;            /*!< RCC clock control register,                                  Address offset: 0x00 */
    volatile uint32_t PLLCFGR;       /*!< RCC PLL configuration register,                              Address offset: 0x04 */
    volatile uint32_t CFGR;          /*!< RCC clock configuration register,                            Address offset: 0x08 */
    volatile uint32_t CIR;           /*!< RCC clock interrupt register,                                Address offset: 0x0C */
    volatile uint32_t AHB1RSTR;      /*!< RCC AHB1 peripheral reset register,                          Address offset: 0x10 */
    volatile uint32_t AHB2RSTR;      /*!< RCC AHB2 peripheral reset register,                          Address offset: 0x14 */
    volatile uint32_t AHB3RSTR;      /*!< RCC AHB3 peripheral reset register,                          Address offset: 0x18 */
    uint32_t      RESERVED0;     /*!< Reserved, 0x1C                                                                    */
    volatile uint32_t APB1RSTR;      /*!< RCC APB1 peripheral reset register,                          Address offset: 0x20 */
    volatile uint32_t APB2RSTR;      /*!< RCC APB2 peripheral reset register,                          Address offset: 0x24 */
    uint32_t      RESERVED1[2];  /*!< Reserved, 0x28-0x2C                                                               */
    volatile uint32_t AHB1ENR;       /*!< RCC AHB1 peripheral clock register,                          Address offset: 0x30 */
    volatile uint32_t AHB2ENR;       /*!< RCC AHB2 peripheral clock register,                          Address offset: 0x34 */
    volatile uint32_t AHB3ENR;       /*!< RCC AHB3 peripheral clock register,                          Address offset: 0x38 */
    uint32_t      RESERVED2;     /*!< Reserved, 0x3C                                                                    */
    volatile uint32_t APB1ENR;       /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x40 */
    volatile uint32_t APB2ENR;       /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x44 */
    uint32_t      RESERVED3[2];  /*!< Reserved, 0x48-0x4C                                                               */
    volatile uint32_t AHB1LPENR;     /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */
    volatile uint32_t AHB2LPENR;     /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */
    volatile uint32_t AHB3LPENR;     /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */
    uint32_t      RESERVED4;     /*!< Reserved, 0x5C                                                                    */
    volatile uint32_t APB1LPENR;     /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */
    volatile uint32_t APB2LPENR;     /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */
    uint32_t      RESERVED5[2];  /*!< Reserved, 0x68-0x6C                                                               */
    volatile uint32_t BDCR;          /*!< RCC Backup domain control register,                          Address offset: 0x70 */
    volatile uint32_t CSR;           /*!< RCC clock control & status register,                         Address offset: 0x74 */
    uint32_t      RESERVED6[2];  /*!< Reserved, 0x78-0x7C                                                               */
    volatile uint32_t SSCGR;         /*!< RCC spread spectrum clock generation register,               Address offset: 0x80 */
    volatile uint32_t PLLI2SCFGR;    /*!< RCC PLLI2S configuration register,                           Address offset: 0x84 */
    volatile uint32_t PLLSAICFGR;    /*!< RCC PLLSAI configuration register,                           Address offset: 0x88 */
    volatile uint32_t DCKCFGR;       /*!< RCC Dedicated Clocks configuration register,                 Address offset: 0x8C */
    volatile uint32_t CKGATENR;      /*!< RCC Clocks Gated Enable Register,                            Address offset: 0x90 */ /* Only for STM32F412xG, STM32413_423xx and STM32F446xx devices */
    volatile uint32_t DCKCFGR2;      /*!< RCC Dedicated Clocks configuration register 2,               Address offset: 0x94 */ /* Only for STM32F410xx, STM32F412xG, STM32413_423xx and STM32F446xx devices */

} RCC_Register_t;

/* Real-Time Clock. */

typedef struct {
    volatile uint32_t TR;      /*!< RTC time register,                                        Address offset: 0x00 */
    volatile uint32_t DR;      /*!< RTC date register,                                        Address offset: 0x04 */
    volatile uint32_t CR;      /*!< RTC control register,                                     Address offset: 0x08 */
    volatile uint32_t ISR;     /*!< RTC initialization and status register,                   Address offset: 0x0C */
    volatile uint32_t PRER;    /*!< RTC prescaler register,                                   Address offset: 0x10 */
    volatile uint32_t WUTR;    /*!< RTC wakeup timer register,                                Address offset: 0x14 */
    volatile uint32_t CALIBR;  /*!< RTC calibration register,                                 Address offset: 0x18 */
    volatile uint32_t ALRMAR;  /*!< RTC alarm A register,                                     Address offset: 0x1C */
    volatile uint32_t ALRMBR;  /*!< RTC alarm B register,                                     Address offset: 0x20 */
    volatile uint32_t WPR;     /*!< RTC write protection register,                            Address offset: 0x24 */
    volatile uint32_t SSR;     /*!< RTC sub second register,                                  Address offset: 0x28 */
    volatile uint32_t SHIFTR;  /*!< RTC shift control register,                               Address offset: 0x2C */
    volatile uint32_t TSTR;    /*!< RTC time stamp time register,                             Address offset: 0x30 */
    volatile uint32_t TSDR;    /*!< RTC time stamp date register,                             Address offset: 0x34 */
    volatile uint32_t TSSSR;   /*!< RTC time-stamp sub second register,                       Address offset: 0x38 */
    volatile uint32_t CALR;    /*!< RTC calibration register,                                 Address offset: 0x3C */
    volatile uint32_t TAFCR;   /*!< RTC tamper and alternate function configuration register, Address offset: 0x40 */
    volatile uint32_t ALRMASSR;/*!< RTC alarm A sub second register,                          Address offset: 0x44 */
    volatile uint32_t ALRMBSSR;/*!< RTC alarm B sub second register,                          Address offset: 0x48 */
    uint32_t RESERVED7;    /*!< Reserved, 0x4C                                                                 */
    volatile uint32_t BKP0R;   /*!< RTC backup register 1,                                    Address offset: 0x50 */
    volatile uint32_t BKP1R;   /*!< RTC backup register 1,                                    Address offset: 0x54 */
    volatile uint32_t BKP2R;   /*!< RTC backup register 2,                                    Address offset: 0x58 */
    volatile uint32_t BKP3R;   /*!< RTC backup register 3,                                    Address offset: 0x5C */
    volatile uint32_t BKP4R;   /*!< RTC backup register 4,                                    Address offset: 0x60 */
    volatile uint32_t BKP5R;   /*!< RTC backup register 5,                                    Address offset: 0x64 */
    volatile uint32_t BKP6R;   /*!< RTC backup register 6,                                    Address offset: 0x68 */
    volatile uint32_t BKP7R;   /*!< RTC backup register 7,                                    Address offset: 0x6C */
    volatile uint32_t BKP8R;   /*!< RTC backup register 8,                                    Address offset: 0x70 */
    volatile uint32_t BKP9R;   /*!< RTC backup register 9,                                    Address offset: 0x74 */
    volatile uint32_t BKP10R;  /*!< RTC backup register 10,                                   Address offset: 0x78 */
    volatile uint32_t BKP11R;  /*!< RTC backup register 11,                                   Address offset: 0x7C */
    volatile uint32_t BKP12R;  /*!< RTC backup register 12,                                   Address offset: 0x80 */
    volatile uint32_t BKP13R;  /*!< RTC backup register 13,                                   Address offset: 0x84 */
    volatile uint32_t BKP14R;  /*!< RTC backup register 14,                                   Address offset: 0x88 */
    volatile uint32_t BKP15R;  /*!< RTC backup register 15,                                   Address offset: 0x8C */
    volatile uint32_t BKP16R;  /*!< RTC backup register 16,                                   Address offset: 0x90 */
    volatile uint32_t BKP17R;  /*!< RTC backup register 17,                                   Address offset: 0x94 */
    volatile uint32_t BKP18R;  /*!< RTC backup register 18,                                   Address offset: 0x98 */
    volatile uint32_t BKP19R;  /*!< RTC backup register 19,                                   Address offset: 0x9C */
} RTC_Register_t;

/* Serial Audio Interface. */

typedef struct {
    volatile uint32_t GCR;      /*!< SAI global configuration register,        Address offset: 0x00 */
} SAI_Register_t;

typedef struct {
    volatile uint32_t CR1;      /*!< SAI block x configuration register 1,     Address offset: 0x04 */
    volatile uint32_t CR2;      /*!< SAI block x configuration register 2,     Address offset: 0x08 */
    volatile uint32_t FRCR;     /*!< SAI block x frame configuration register, Address offset: 0x0C */
    volatile uint32_t SLOTR;    /*!< SAI block x slot register,                Address offset: 0x10 */
    volatile uint32_t IMR;      /*!< SAI block x interrupt mask register,      Address offset: 0x14 */
    volatile uint32_t SR;       /*!< SAI block x status register,              Address offset: 0x18 */
    volatile uint32_t CLRFR;    /*!< SAI block x clear flag register,          Address offset: 0x1C */
    volatile uint32_t DR;       /*!< SAI block x data register,                Address offset: 0x20 */
} SAI_Block_Register_t;

/* SD Host Interface. */

typedef struct {
    volatile uint32_t POWER;          /*!< SDIO power control register,    Address offset: 0x00 */
    volatile uint32_t CLKCR;          /*!< SDI clock control register,     Address offset: 0x04 */
    volatile uint32_t ARG;            /*!< SDIO argument register,         Address offset: 0x08 */
    volatile uint32_t CMD;            /*!< SDIO command register,          Address offset: 0x0C */
    volatile uint32_t  RESPCMD;        /*!< SDIO command response register, Address offset: 0x10 */
    volatile uint32_t  RESP1;          /*!< SDIO response 1 register,       Address offset: 0x14 */
    volatile uint32_t  RESP2;          /*!< SDIO response 2 register,       Address offset: 0x18 */
    volatile uint32_t  RESP3;          /*!< SDIO response 3 register,       Address offset: 0x1C */
    volatile uint32_t  RESP4;          /*!< SDIO response 4 register,       Address offset: 0x20 */
    volatile uint32_t DTIMER;         /*!< SDIO data timer register,       Address offset: 0x24 */
    volatile uint32_t DLEN;           /*!< SDIO data length register,      Address offset: 0x28 */
    volatile uint32_t DCTRL;          /*!< SDIO data control register,     Address offset: 0x2C */
    volatile uint32_t  DCOUNT;         /*!< SDIO data counter register,     Address offset: 0x30 */
    volatile uint32_t  STA;            /*!< SDIO status register,           Address offset: 0x34 */
    volatile uint32_t ICR;            /*!< SDIO interrupt clear register,  Address offset: 0x38 */
    volatile uint32_t MASK;           /*!< SDIO mask register,             Address offset: 0x3C */
    uint32_t      RESERVED0[2];   /*!< Reserved, 0x40-0x44                                  */
    volatile uint32_t  FIFOCNT;        /*!< SDIO FIFO counter register,     Address offset: 0x48 */
    uint32_t      RESERVED1[13];  /*!< Reserved, 0x4C-0x7C                                  */
    volatile uint32_t FIFO;           /*!< SDIO data FIFO register,        Address offset: 0x80 */
} SDIO_Register_t;

/* Serial Peripheral Interface. */

typedef struct {
    volatile uint16_t CR1;        /*!< SPI control register 1 (not used in I2S mode),      Address offset: 0x00 */
    uint16_t      RESERVED0;  /*!< Reserved, 0x02                                                           */
    volatile uint16_t CR2;        /*!< SPI control register 2,                             Address offset: 0x04 */
    uint16_t      RESERVED1;  /*!< Reserved, 0x06                                                           */
    volatile uint16_t SR;         /*!< SPI status register,                                Address offset: 0x08 */
    uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                                           */
    volatile uint16_t DR;         /*!< SPI data register,                                  Address offset: 0x0C */
    uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                                           */
    volatile uint16_t CRCPR;      /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */
    uint16_t      RESERVED4;  /*!< Reserved, 0x12                                                           */
    volatile uint16_t RXCRCR;     /*!< SPI RX CRC register (not used in I2S mode),         Address offset: 0x14 */
    uint16_t      RESERVED5;  /*!< Reserved, 0x16                                                           */
    volatile uint16_t TXCRCR;     /*!< SPI TX CRC register (not used in I2S mode),         Address offset: 0x18 */
    uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                                           */
    volatile uint16_t I2SCFGR;    /*!< SPI_I2S configuration register,                     Address offset: 0x1C */
    uint16_t      RESERVED7;  /*!< Reserved, 0x1E                                                           */
    volatile uint16_t I2SPR;      /*!< SPI_I2S prescaler register,                         Address offset: 0x20 */
    uint16_t      RESERVED8;  /*!< Reserved, 0x22                                                           */
} SPI_Register_t;

/* Timer. */

typedef struct {
    volatile uint16_t CR1;         /*!< TIM control register 1,              Address offset: 0x00 */
    uint16_t      RESERVED0;   /*!< Reserved, 0x02                                            */
    volatile uint16_t CR2;         /*!< TIM control register 2,              Address offset: 0x04 */
    uint16_t      RESERVED1;   /*!< Reserved, 0x06                                            */
    volatile uint16_t SMCR;        /*!< TIM slave mode control register,     Address offset: 0x08 */
    uint16_t      RESERVED2;   /*!< Reserved, 0x0A                                            */
    volatile uint16_t DIER;        /*!< TIM DMA/interrupt enable register,   Address offset: 0x0C */
    uint16_t      RESERVED3;   /*!< Reserved, 0x0E                                            */
    volatile uint16_t SR;          /*!< TIM status register,                 Address offset: 0x10 */
    uint16_t      RESERVED4;   /*!< Reserved, 0x12                                            */
    volatile uint16_t EGR;         /*!< TIM event generation register,       Address offset: 0x14 */
    uint16_t      RESERVED5;   /*!< Reserved, 0x16                                            */
    volatile uint16_t CCMR1;       /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
    uint16_t      RESERVED6;   /*!< Reserved, 0x1A                                            */
    volatile uint16_t CCMR2;       /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
    uint16_t      RESERVED7;   /*!< Reserved, 0x1E                                            */
    volatile uint16_t CCER;        /*!< TIM capture/compare enable register, Address offset: 0x20 */
    uint16_t      RESERVED8;   /*!< Reserved, 0x22                                            */
    volatile uint32_t CNT;         /*!< TIM counter register,                Address offset: 0x24 */
    volatile uint16_t PSC;         /*!< TIM prescaler,                       Address offset: 0x28 */
    uint16_t      RESERVED9;   /*!< Reserved, 0x2A                                            */
    volatile uint32_t ARR;         /*!< TIM auto-reload register,            Address offset: 0x2C */
    volatile uint16_t RCR;         /*!< TIM repetition counter register,     Address offset: 0x30 */
    uint16_t      RESERVED10;  /*!< Reserved, 0x32                                            */
    volatile uint32_t CCR1;        /*!< TIM capture/compare register 1,      Address offset: 0x34 */
    volatile uint32_t CCR2;        /*!< TIM capture/compare register 2,      Address offset: 0x38 */
    volatile uint32_t CCR3;        /*!< TIM capture/compare register 3,      Address offset: 0x3C */
    volatile uint32_t CCR4;        /*!< TIM capture/compare register 4,      Address offset: 0x40 */
    volatile uint16_t BDTR;        /*!< TIM break and dead-time register,    Address offset: 0x44 */
    uint16_t      RESERVED11;  /*!< Reserved, 0x46                                            */
    volatile uint16_t DCR;         /*!< TIM DMA control register,            Address offset: 0x48 */
    uint16_t      RESERVED12;  /*!< Reserved, 0x4A                                            */
    volatile uint16_t DMAR;        /*!< TIM DMA address for full transfer,   Address offset: 0x4C */
    uint16_t      RESERVED13;  /*!< Reserved, 0x4E                                            */
    volatile uint16_t OR;          /*!< TIM option register,                 Address offset: 0x50 */
    uint16_t      RESERVED14;  /*!< Reserved, 0x52                                            */
} TIM_Register_t;

/* Universal Synchoronous Asynchoronous Receiver Transmitter. */

typedef struct {
    volatile uint16_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
    uint16_t      RESERVED0;  /*!< Reserved, 0x02                                                */
    volatile uint16_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
    uint16_t      RESERVED1;  /*!< Reserved, 0x06                                                */
    volatile uint16_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
    uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                                */
    volatile uint16_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
    uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                                */
    volatile uint16_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
    uint16_t      RESERVED4;  /*!< Reserved, 0x12                                                */
    volatile uint16_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
    uint16_t      RESERVED5;  /*!< Reserved, 0x16                                                */
    volatile uint16_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
    uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                                */
} USART_Register_t;

/* Window Watchdog. */

typedef struct {
    volatile uint32_t CR;   /*!< WWDG Control register,       Address offset: 0x00 */
    volatile uint32_t CFR;  /*!< WWDG Configuration register, Address offset: 0x04 */
    volatile uint32_t SR;   /*!< WWDG Status register,        Address offset: 0x08 */
} WWDG_Register_t;

/* Crypto Processor. */

typedef struct {
    volatile uint32_t CR;         /*!< CRYP control register,                                    Address offset: 0x00 */
    volatile uint32_t SR;         /*!< CRYP status register,                                     Address offset: 0x04 */
    volatile uint32_t DR;         /*!< CRYP data input register,                                 Address offset: 0x08 */
    volatile uint32_t DOUT;       /*!< CRYP data output register,                                Address offset: 0x0C */
    volatile uint32_t DMACR;      /*!< CRYP DMA control register,                                Address offset: 0x10 */
    volatile uint32_t IMSCR;      /*!< CRYP interrupt mask set/clear register,                   Address offset: 0x14 */
    volatile uint32_t RISR;       /*!< CRYP raw interrupt status register,                       Address offset: 0x18 */
    volatile uint32_t MISR;       /*!< CRYP masked interrupt status register,                    Address offset: 0x1C */
    volatile uint32_t K0LR;       /*!< CRYP key left  register 0,                                Address offset: 0x20 */
    volatile uint32_t K0RR;       /*!< CRYP key right register 0,                                Address offset: 0x24 */
    volatile uint32_t K1LR;       /*!< CRYP key left  register 1,                                Address offset: 0x28 */
    volatile uint32_t K1RR;       /*!< CRYP key right register 1,                                Address offset: 0x2C */
    volatile uint32_t K2LR;       /*!< CRYP key left  register 2,                                Address offset: 0x30 */
    volatile uint32_t K2RR;       /*!< CRYP key right register 2,                                Address offset: 0x34 */
    volatile uint32_t K3LR;       /*!< CRYP key left  register 3,                                Address offset: 0x38 */
    volatile uint32_t K3RR;       /*!< CRYP key right register 3,                                Address offset: 0x3C */
    volatile uint32_t IV0LR;      /*!< CRYP initialization vector left-word  register 0,         Address offset: 0x40 */
    volatile uint32_t IV0RR;      /*!< CRYP initialization vector right-word register 0,         Address offset: 0x44 */
    volatile uint32_t IV1LR;      /*!< CRYP initialization vector left-word  register 1,         Address offset: 0x48 */
    volatile uint32_t IV1RR;      /*!< CRYP initialization vector right-word register 1,         Address offset: 0x4C */
    volatile uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0,        Address offset: 0x50 */
    volatile uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1,        Address offset: 0x54 */
    volatile uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2,        Address offset: 0x58 */
    volatile uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3,        Address offset: 0x5C */
    volatile uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4,        Address offset: 0x60 */
    volatile uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5,        Address offset: 0x64 */
    volatile uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6,        Address offset: 0x68 */
    volatile uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7,        Address offset: 0x6C */
    volatile uint32_t CSGCM0R;    /*!< CRYP GCM/GMAC context swap register 0,                    Address offset: 0x70 */
    volatile uint32_t CSGCM1R;    /*!< CRYP GCM/GMAC context swap register 1,                    Address offset: 0x74 */
    volatile uint32_t CSGCM2R;    /*!< CRYP GCM/GMAC context swap register 2,                    Address offset: 0x78 */
    volatile uint32_t CSGCM3R;    /*!< CRYP GCM/GMAC context swap register 3,                    Address offset: 0x7C */
    volatile uint32_t CSGCM4R;    /*!< CRYP GCM/GMAC context swap register 4,                    Address offset: 0x80 */
    volatile uint32_t CSGCM5R;    /*!< CRYP GCM/GMAC context swap register 5,                    Address offset: 0x84 */
    volatile uint32_t CSGCM6R;    /*!< CRYP GCM/GMAC context swap register 6,                    Address offset: 0x88 */
    volatile uint32_t CSGCM7R;    /*!< CRYP GCM/GMAC context swap register 7,                    Address offset: 0x8C */
} CRYP_Register_t;

/* Hash. */

typedef struct {
    volatile uint32_t CR;               /*!< HASH control register,          Address offset: 0x00        */
    volatile uint32_t DIN;              /*!< HASH data input register,       Address offset: 0x04        */
    volatile uint32_t STR;              /*!< HASH start register,            Address offset: 0x08        */
    volatile uint32_t HR[5];            /*!< HASH digest registers,          Address offset: 0x0C-0x1C   */
    volatile uint32_t IMR;              /*!< HASH interrupt enable register, Address offset: 0x20        */
    volatile uint32_t SR;               /*!< HASH status register,           Address offset: 0x24        */
    uint32_t RESERVED[52];     /*!< Reserved, 0x28-0xF4                                         */
    volatile uint32_t CSR[54];          /*!< HASH context swap registers,    Address offset: 0x0F8-0x1CC */
} HASH_Register_t;

typedef struct {
    volatile uint32_t HR[8];     /*!< HASH digest registers,          Address offset: 0x310-0x32C */ 
} HASH_DIGEST_Register_t;

/* RNG. */

typedef struct {
    volatile uint32_t CR;  /*!< RNG control register, Address offset: 0x00 */
    volatile uint32_t SR;  /*!< RNG status register,  Address offset: 0x04 */
    volatile uint32_t DR;  /*!< RNG data register,    Address offset: 0x08 */
} RNG_Register_t;

/************ System ************/

class System {
public:
    enum class ClockBus {
        AHB1 = 0,
        AHB2 = 1,
        AHB3 = 2,
        APB1 = 3,
        APB2 = 4,
    };

    enum class ClockChannel {
        /* AHB1. */
        GPIOA = 0 + (32 * (int)ClockBus::AHB1),
        GPIOB = 1 + (32 * (int)ClockBus::AHB1),
        GPIOC = 2 + (32 * (int)ClockBus::AHB1),
        GPIOD = 3 + (32 * (int)ClockBus::AHB1),
        GPIOE = 4 + (32 * (int)ClockBus::AHB1),
        GPIOF = 5 + (32 * (int)ClockBus::AHB1),
        GPIOG = 6 + (32 * (int)ClockBus::AHB1),
        GPIOH = 7 + (32 * (int)ClockBus::AHB1),
        GPIOI = 8 + (32 * (int)ClockBus::AHB1),
        CRC = 12 + (32 * (int)ClockBus::AHB1),
        BKP_SRAM = 18 + (32 * (int)ClockBus::AHB1),
        CCM_DATA_RAM = 20 + (32 * (int)ClockBus::AHB1),
        DMA1 = 21 + (32 * (int)ClockBus::AHB1),
        DMA2 = 22 + (32 * (int)ClockBus::AHB1),
        ETH_MAC = 25 + (32 * (int)ClockBus::AHB1),
        ETH_MAC_TX = 26 + (32 * (int)ClockBus::AHB1),
        ETH_MAC_RX = 27 + (32 * (int)ClockBus::AHB1),
        ETH_MAC_PTP = 28 + (32 * (int)ClockBus::AHB1),
        OTG_HS = 29 + (32 * (int)ClockBus::AHB1),
        OTG_HS_ULPI = 30 + (32 * (int)ClockBus::AHB1),
        /* AHB2. */
        DCMI = 0 + (32 * (int)ClockBus::AHB2),
        CRYP = 4 + (32 * (int)ClockBus::AHB2),
        HASH = 5 + (32 * (int)ClockBus::AHB2),
        RNG = 6 + (32 * (int)ClockBus::AHB2),
        OTG_FS = 7 + (32 * (int)ClockBus::AHB2),
        /* AHB3. */
        FSMC = 0 + (32 * (int)ClockBus::AHB3),
        /* APB1. */
        TIM2 = 0 + (32 * (int)ClockBus::APB1),
        TIM3 = 1 + (32 * (int)ClockBus::APB1),
        TIM4 = 2 + (32 * (int)ClockBus::APB1),
        TIM5 = 3 + (32 * (int)ClockBus::APB1),
        TIM6 = 4 + (32 * (int)ClockBus::APB1),
        TIM7 = 5 + (32 * (int)ClockBus::APB1),
        TIM12 = 6 + (32 * (int)ClockBus::APB1),
        TIM13 = 7 + (32 * (int)ClockBus::APB1),
        TIM14 = 8 + (32 * (int)ClockBus::APB1),
        WWDG = 11 + (32 * (int)ClockBus::APB1),
        SPI2 = 14 + (32 * (int)ClockBus::APB1),
        SPI3 = 15 + (32 * (int)ClockBus::APB1),
        USART2 = 17 + (32 * (int)ClockBus::APB1),
        USART3 = 18 + (32 * (int)ClockBus::APB1),
        UART4 = 19 + (32 * (int)ClockBus::APB1),
        UART5 = 20 + (32 * (int)ClockBus::APB1),
        I2C1 = 21 + (32 * (int)ClockBus::APB1),
        I2C2 = 22 + (32 * (int)ClockBus::APB1),
        I2C3 = 23 + (32 * (int)ClockBus::APB1),
        CAN1 = 25 + (32 * (int)ClockBus::APB1),
        CAN2 = 26 + (32 * (int)ClockBus::APB1),
        PWR = 28 + (32 * (int)ClockBus::APB1),
        DAC = 29 + (32 * (int)ClockBus::APB1),
        /* APB2. */
        TIM1 = 0 + (32 * (int)ClockBus::APB2),
        TIM8 = 1 + (32 * (int)ClockBus::APB2),
        USART1 = 4 + (32 * (int)ClockBus::APB2),
        USART6 = 5 + (32 * (int)ClockBus::APB2),
        ADC1 = 8 + (32 * (int)ClockBus::APB2),
        ADC2 = 9 + (32 * (int)ClockBus::APB2),
        ADC3 = 10 + (32 * (int)ClockBus::APB2),
        SDIO = 11 + (32 * (int)ClockBus::APB2),
        SPI1 = 12 + (32 * (int)ClockBus::APB2),
        SYSCFG = 14 + (32 * (int)ClockBus::APB2),
        TIM9 = 16 + (32 * (int)ClockBus::APB2),
        TIM10 = 17 + (32 * (int)ClockBus::APB2),
        TIM11 = 18 + (32 * (int)ClockBus::APB2),
    };

    enum class InterruptChannel {
        NonMaskableInt = -14,
        MemoryManagement = -12,
        BusFault = -11,
        UsageFault = -10,
        SVCall = -5,
        DebugMonitor = -4,
        PendSV = -2,
        SysTick = -1,
        WWDG = 0,
        PVD = 1,
        TAMP_STAMP = 2,
        RTC_WKUP = 3,
        FLASH = 4,
        RCC = 5,
        EXTI0 = 6,
        EXTI1 = 7,
        EXTI2 = 8,
        EXTI3 = 9,
        EXTI4 = 10,
        DMA1_Stream0 = 11,
        DMA1_Stream1 = 12,
        DMA1_Stream2 = 13,
        DMA1_Stream3 = 14,
        DMA1_Stream4 = 15,
        DMA1_Stream5 = 16,
        DMA1_Stream6 = 17,
        ADC = 18,
        CAN1_TX = 19,
        CAN1_RX0 = 20,
        CAN1_RX1 = 21,
        CAN1_SCE = 22,
        EXTI9_5 = 23,
        TIM1_BRK_TIM9 = 24,
        TIM1_UP_TIM10 = 25,
        TIM1_TRG_COM_TIM11 = 26,
        TIM1_CC = 27,
        TIM2 = 28,
        TIM3 = 29,
        TIM4 = 30,
        I2C1_EV = 31,
        I2C1_ER = 32,
        I2C2_EV = 33,
        I2C2_ER = 34,
        SPI1 = 35,
        SPI2 = 36,
        USART1 = 37,
        USART2 = 38,
        USART3 = 39,
        EXTI15_10 = 40,
        RTC_Alarm = 41,
        OTG_FS_WKUP = 42,
        TIM8_BRK_TIM12 = 43,
        TIM8_UUP_TIM13 = 44,
        TIM8_TRG_COM_TIM14 = 45,
        TIM8_CC = 46,
        DMA1_Stream7 = 47,
        FSMC = 48,
        SDIO = 49,
        TIM5 = 50,
        SPI3 = 51,
        UART4 = 52,
        UART5 = 53,
        TIM6_DAC = 54,
        TIM7 = 55,
        DMA2_Stream0 = 56,
        DMA2_Stream1 = 57,
        DMA2_Stream2 = 58,
        DMA2_Stream3 = 59,
        DMA2_Stream4 = 60,
        ETH = 61,
        ETH_WKUP = 62,
        CAN2_TX = 63,
        CAN2_RX0 = 64,
        CAN2_RX1 = 65,
        CAN2_SCE = 66,
        OTG_FS = 67,
        DMA2_Stream5 = 68,
        DMA2_Stream6 = 69,
        DMA2_Stream7 = 70,
        USART6 = 71,
        I2C3_EV = 72,
        I2C3_ER = 73,
        OTG_HS_EP1_OUT = 74,
        OTG_HS_EP1_IN = 75,
        OTG_HS_WKUP = 76,
        OTG_HS = 77,
        DCMI = 78,
        CRYP = 79,
        HASH_RNG = 80,
        FPU = 81,
    };

    typedef void (*InterruptCallback)(void *user_data);

    struct InterruptResource {
        InterruptCallback callback;
        void *user_data;
    };

    
public:
    /* About clocks. */
    static void initClock();
    static bool setClockChannelStatus(ClockChannel channel,bool status);
    static bool getClockChannelStatus(ClockChannel channel);
    static unsigned int getClockChannelFrequency(ClockChannel channel);

    /* About interrupts. */
    static bool setInterruptChannelStatus(InterruptChannel channel,bool status);
    static bool setInterruptChannelStatus(int channel,bool status);
    static bool getInterruptChannelStatus(InterruptChannel channel);
    static bool getInterruptChannelStatus(int channel);
    static bool addInterruptCallback(InterruptChannel channel,InterruptCallback callback,void *user_data);

    /* System delay. */
    static void delayMs(unsigned int nms);

public:
    volatile static unsigned long int tick;
    static InterruptResource interrupt_resources[128];
private:
    static unsigned int clock_bus_frequencies[5];
};

#endif
